const $ = e => document.querySelector(e);
let nm, pwd, fname, mrk = {}, dopDT = [], mrkPup = {}, topPup = {},
    dtNow = (new Date()).toISOString().split('T')[0];
document.title = TEACH;

// Преобразование даты 2025-03-12 к виду 12.03 с заменой
// дат промежуточной аттестации на их названия из config.js
const dtRus = dt => {
   return Object.keys(DOP).includes(dt) ? DOP[dt] :
          dt.replace(/(\d+)-(\d+)-(\d+)/, "$3.$2")
};

// Заполняем селект выбора предмета
let selSubj = '';
Object.keys(subjs).forEach(
   k => selSubj += `<option value="${k}">${subjs[k]}</option>`
);
$("#subj").innerHTML = selSubj;

// *************************************************************
// Первичная авторизация клиента
const auth = async () => {
   fname = $("#fname").value.trim().replace(/\s{2,}/g, ' ');
   fname = fname.includes(' ') ? fname : TEACH;
   nm = fname.replace(' ', '_');
   pwd = $("#pwd").value.trim();
   if (!nm || !pwd) {
      $("header output").innerHTML = "Введите данные!";
      return;
   }
   $("header output").innerHTML = "Ждите...";
   const resp = await (await fetch(
      `api.php?f=auth&nm=${nm}&pwd=${pwd}`
   )).text();
   if (resp !== "success") {
      $("header output").innerHTML = "Ошибка авторизации";
      return;
   }
   $("header output").innerHTML = "Введите имя и пароль";
   $("header").style.display = "none";
   $("main").style.display = "block";
   $("h1").innerHTML = fname;
   show();
},

// *************************************************************
// Ввод/редактирование темы урока
sv = async () => {
   // Дата, тема, домашнее задание, к-во часов, вес отметок
   let [dt, sb, tp, ht, val, wt] =
      ["#dt", "#subj", "#topUr", "#htask", "#val", "#wgh"]
      .map(f => $(f).value.replace(/\s+/g, ' ').trim());
   if (!tp) if (!confirm("Колонка отметок будет удалена. Вы уверены?")) return;
   const resp = await (await fetch(`api.php?f=svtopic&nm=${nm}&pwd=${pwd}`, {
      method: "POST", body: `${dt}¤${sb}¤${tp}¤${ht}¤${val}¤${wt}`
   })).text();
   if (resp !== "success") alert("Ошибка. Тема не сохранена");
   else {
      show();
      $("#dt").value    = dtNow;
      $("#topUr").value = '';  $("#htask").value = '';
      $("#val").value   = '2'; $("#wgh").value   = '1';
   }
},

// *************************************************************
// Показ списка тем по данному предмету
showTopics = async sb => {
   const resp = await (await fetch(
      `api.php?f=showtpcs&nm=${nm}&pwd=${pwd}&sb=${sb}`
   )).text();
   if (!resp.includes("success")) alert("Ошибка. Темы не загружены");
   else {
      $("article").innerHTML = resp.replace("success", '');
      let vsego = 0;
      for (let p of $("article").children)
         for (let c of p.children) if (c.className == "vol")
            vsego += Number(c.innerHTML);
      $("article").innerHTML +=
         `<p class="vsego">Всего часов: <b>${vsego}</b></p>`;
      $("article").scrollTop = $("article").scrollHeight;
   }
}

// *************************************************************
// Подстановка данных темы урока в поля ввода сверху
uptpc = dt => {
   let p = $('#t' + dt);
   $("#dt").value = dt;
   $("#htask").value = '';
   for (let n of p.children) {      
      if (n.className == "topic")  $("#topUr").value = n.innerHTML;
      if (n.className == "home")
         $("#htask").value = n.innerHTML.replace(/(^\[)|(\]$)/g, '');
      if (n.className == "vol")    $("#val").value   = n.innerHTML;
      if (n.className == "weight") $("#wgh").value   = n.innerHTML;
   }
},

// Получение и выдача таблицы с отметками по данному предмету
getMarks = async sb => {
   // Получаем JSON с отметками
   const resp = await (await fetch(
      `api.php?f=allmrk&nm=${nm}&pwd=${pwd}&sb=${sb}`
   )).text();
   if (!resp.includes("success")) alert("Ошибка. Отметки не загружены");
   else {
      mrk = JSON.parse(resp.replace("success", '').replace(/,}$/, '}'));
      dopDT = Object.keys(DOP); // даты отметок ПА из config.js
      let  dtArr = [...new Set([...Object.keys(mrk), ...dopDT])].sort(),
           out = "<div id='marks'><table><tr>";
      dtArr.forEach(dt => { // строка с датами
         let k = dopDT.includes(dt) ? " class='pa'" : '';
         out += `<td${k}>${dtRus(dt)}</td>`
      });
      out += "</tr><tr class='w'>";
      dtArr.forEach(dt => { // строка с весами отметок
         let k = dopDT.includes(dt) ? " class='pa'" : '';
         if (mrk[dt]) out += `<td${k}>${mrk[dt].w || ' '}</td>`;
         else         out += `<td> </td>`;
      });
      out += "</tr>";
      for (let pup of PUP) {
         out += "<tr>";
         dtArr.forEach(dt => { // строка с отметками одного ученика
            let strong = dopDT.includes(dt) ? " class='pa'" : '';
            if (mrk[dt])
               out += `<td${strong} onclick=`
                    + `"inp('${pup}', '${dt}', this)">`
                    + `${mrk[dt][pup] || ''}</td>`;
            else
               out += `<td${strong} onclick="inp('${pup}', '${dt}', this)">`
                    + `</td>`;
         });
         out += "</tr>";
      }
      return out+"</table></div>";
   }
},

// *************************************************************
// Превращение ячейки в поле input при кликании на ней
inp = (pup, dt, tdObj) => {
   let m = tdObj.innerHTML.trim(); // существующая (старая) отметка
   tdObj.style.paddingLeft  = "0";
   tdObj.style.paddingRight = "0";
   tdObj.innerHTML =
      `<input class="mrk" value="${tdObj.innerHTML}" `
    + `onblur="putMrk(this, '${pup}', '${dt}', this.value, '${m}', false)" `
    + `onKeyDown="if (event.code == 'Enter' || event.code == 'ArrowDown') `
    + `putMrk(this, '${pup}', '${dt}', this.value, '${m}', true)">`;
   tdObj.children[0].focus();
   tdObj.onclick = null;
},

// *************************************************************
// Перемещение на ячейку вниз по таблице отметок
// Аргумент - объект текущей ячейки, результат - фокус на новой
downTD = objectTD => {
   // Вычисляем номер ячейки в строке (n)
   let tds = objectTD.parentNode.children, n=-1;
   for (let i=-1; i<tds.length; i++) if (tds[i] === objectTD) {n=i; break;}
   
   // Вычисляем номер строки в таблице (k)
   let tr = objectTD.parentNode, trs = tr.parentNode.children, k=-1;
   for (let i=-1; i<trs.length; i++) if (trs[i] === tr) {k=i; break;}
   
   // Перемещаемся
   let newTR = trs[k+1];
   if (newTR) newTR.children[n].click();
   else       objectTD.blur();
},

// *************************************************************
// Отправка содержимого ячейки на сервер при потере фокуса
// Последний аргумент - нужно ли перемещаться на ячейку вниз
putMrk = async (inpObj, pup, dt, mark, markOld, downtd) => {
   mark = mark.replace('o', 'о').replace(/[^0-9 но+=\-]/g, '').trim();
   let tdObj = inpObj.parentNode;      

   // Отправляем на сервер
   if (mark != markOld) {
      inpObj.style.background = "#fee";
      let mr = encodeURIComponent(mark),
          sb = $("#subj").value.trim();
      const resp = await (await fetch(
         `api.php?f=putmark&`
       + `nm=${nm}&pwd=${pwd}&sb=${sb}&pup=${pup}&dt=${dt}&mrk=${mr}`
      )).text();
      if (resp != "success") {
         tdObj.innerHTML = "ERR";
         setTimeout(() => tdObj.innerHTML = '', 2000);
      }
      else {
         tdObj.innerHTML = mark;         
         mrk[dt][pup] = mark; // добавляем отметку в объект mrk
      }
   }
   else tdObj.innerHTML = mark;

   tdObj.style.paddingLeft  = "8px";
   tdObj.style.paddingRight = "8px";
   tdObj.onclick = () => inp(pup, dt, tdObj);
   if (downtd) downTD(tdObj);
},

// ***************************************************************
// Показ статистики по данному ребенку (даты ПА - в массиве dopDT)
stat = pup => {
   $("in-fo h4").innerHTML = pup.replace('_', ' ');
   let sr = {}; nb = {}; op = {}; sum = {}; n = {}; kvo = {};

   for (let dt of Object.keys(mrk)) {
      if (dopDT.includes(dt)) continue;
      if (!mrk[dt]) continue;
      if (!Object.keys(mrk[dt]).includes(pup)) continue;
      let markFull = mrk[dt][pup].trim().replace(/\s{2,}/g, ' '),
             nebil = markFull.split('н').length - 1,
             opozd = markFull.split('о').length - 1,
         markDigit = markFull.replace(/[^ \-0-9]/g, '');
         markDigit = markDigit.includes('-') ?
                     markDigit.split('-')[1] : markDigit;
      let mrkArr = markDigit.split(' ');
      let summa = 0, kolvo = 0;
      mrkArr.forEach(m => {
         if (m) {
            summa += Number(m) * Number(mrk[dt].w);
            kolvo += Number(mrk[dt].w);
         }
      });
      dopDT.forEach(dPA => {
         let dtStart = START[dopDT.indexOf(dPA)] == -1 ?
                       "2000-00-00" : dopDT[START[dopDT.indexOf(dPA)]];
         if (dt > dtStart && dt < dPA) {
            nb[DOP[dPA]] = nb[DOP[dPA]] ?
                           nb[DOP[dPA]] + nebil : nebil;
            op[DOP[dPA]] = op[DOP[dPA]] ?
                           op[DOP[dPA]] + opozd : opozd;
           sum[DOP[dPA]] = sum[DOP[dPA]] ?
                           sum[DOP[dPA]] + summa : summa;
           kvo[DOP[dPA]] = kvo[DOP[dPA]] ?
                           kvo[DOP[dPA]] + kolvo : kolvo;
         }
      });
   }  
   Object.values(DOP).forEach(p => {
      sr[p] = kvo[p] ? (sum[p]/kvo[p]).toFixed(2) : "нет"
   });

   let inn = "<tr><th>&nbsp;</th><th>Сред</th><th>н</th><th>оп</th></tr>";
   Object.values(DOP).forEach(per => {
      inn += `<tr><td>${per}</td><td>${sr[per] || "нет"}</td>`
           + `<td>${nb[per] || "нет"}</td><td>${op[per] || "нет"}</td></tr>`
   });
   $("in-fo table").innerHTML = inn;
   $("in-fo").style.display = "block";
},

// **********************************************************************
// Получение и выдача таблиц (отметки+темы; статистика) по одному ребенку
onePup = async subj => {
   let out = '';

   // Получаем данные, если они не получены ранее
   if (!Object.keys(mrkPup).length || !Object.keys(topPup).length) {
      const resp = await (await fetch(
         `api.php?f=onepup&nm=${nm}&pwd=${pwd}`)).text();
      if (!resp.includes("success")) return "Ошибка. Не могу получить данные."
      let respArr = resp.replace(/^success/,'').replace(/,}/g,'}').split('¤');
      mrkPup = JSON.parse(respArr[0]);
      topPup = JSON.parse(respArr[1]);
   }
   if (!mrkPup[subj]) {
      out += "<p>Отметок пока нет</p>";
      return out;
   }

   // Таблица с отметками
   out += "<table id='pup'><tr><th>Дата</th><th>Вес</th><th>Тема</th>"
        + "<th>ДЗ</th><th>Тетр</th><th>Отм</th></tr>";
   for (let dt of Object.keys(mrkPup[subj]).sort()) {
      let stl = Object.keys(DOP).includes(dt) ? " class='pap'" : '',
            m = mrkPup[subj][dt],
            ntb, otm;
      if (m.includes('-')) [ntb, otm] = m.replace(/[+=но]/g, '').split('-');
      else                 [ntb, otm] = ['', m.replace(/[+=но]/g, '')];
      ntb = m.includes('+') ? "100" : ntb;
      ntb = m.includes('=') ? "нет" : ntb;
      otm = (m.replace(/[+= 0-9\-]/g, '') + otm).replace(/ /g, "&nbsp;");
      if (ntb !== '' && ntb !== "нет") ntb += '%';

      let w, tpk = '', h = '';
      if (!topPup[subj]) w = '';
      else if (!topPup[subj][dt]) w = '';
      else [w, tpk, h] = topPup[subj][dt];
      w = Number(w) == 1 ? '' : w; 

      out += `<tr${stl}><td>${dtRus(dt)}</td><td>${w}</td><td>${tpk}</td>`
           + `<td>${h}</td><td>${ntb}</td><td>${otm}</td></tr>`;
   }
   out += "</table>";

   out += "<h2>Средневзвешенные баллы,<br>пропуски уроков и опоздания</h2>";

   // Таблица со статистикой
   let sr = {}, prop = {}, opzd = {}, sum = {}, kvo = {};
   for (let dt of Object.keys(mrkPup[subj])) {
      if (Object.keys(DOP).includes(dt)) continue;
      if (!mrkPup[subj][dt]) continue;
      let markFull = mrkPup[subj][dt].trim().replace(/\s{2,}/g, ' '),
             nebil = markFull.split('н').length - 1,
             opozd = markFull.split('о').length - 1,
         markDigit = markFull.replace(/[^ \-0-9]/g, '');
         markDigit = markDigit.includes('-') ?
                     markDigit.split('-')[1] : markDigit;
      let mrkArr = markDigit.split(' ');
      let summa = 0, kolvo = 0;
      mrkArr.forEach(m => {
         if (m) {
            summa += Number(m) * Number(topPup[subj][dt][0]);
            kolvo += Number(topPup[subj][dt][0]);
         }
      });
      let dopDT = Object.keys(DOP);
      dopDT.forEach(dPA => {
         let dtStart = START[Object.keys(DOP).indexOf(dPA)] == -1 ?
                       "2000-00-00" : dopDT[START[dopDT.indexOf(dPA)]];
         if (dt > dtStart && dt < dPA) {
            prop[DOP[dPA]] = prop[DOP[dPA]] ?
                             prop[DOP[dPA]] + nebil : nebil;
            opzd[DOP[dPA]] = opzd[DOP[dPA]] ?
                             opzd[DOP[dPA]] + opozd : opozd;
            sum[DOP[dPA]]  = sum[DOP[dPA]] ?
                             sum[DOP[dPA]] + summa : summa;
            kvo[DOP[dPA]]  = kvo[DOP[dPA]] ?
                             kvo[DOP[dPA]] + kolvo : kolvo;
         }
      });
   }  
   Object.values(DOP).forEach(p => {
      sr[p] = kvo[p] ? (sum[p]/kvo[p]).toFixed(2) : "нет"
   });

   out += "<table id='stat'><tr><th>&nbsp;</th><th>Сред</th>"
        + "<th>Проп</th><th>Оп</th></tr>";
   for (let [dt, paPer] of Object.entries(DOP)) {
      out += `<tr><td>${paPer}</td><td>${sr[paPer] || "нет"}</td>`
           + `<td>${prop[paPer] || "нет"}</td>`
           + `<td>${opzd[paPer] || "нет"}</td></tr>`;
   }
   out += "</table>";
   
   return out;
},

// *************************************************************
// Показ содержимого страницы
show = async () => {
   // Выбранный предмет
   let subj = $("#subj").value.trim();

   // Если это учитель - формируем блоки отметок и тем
   if (fname == TEACH) {
      // Список учащихся и таблица с отметками
      let list =
         "<table id='list'><tr><td>Дата</td></tr><tr><td>Вес</td></tr>";
      for (let i=0; i<PUP.length; i++)
         list += `<tr><td onclick="stat('${PUP[i]}')">`
               + `<tt>${(i+1).toString().padStart(2, ' ')}</tt>.`
               + ` ${PUP[i].replace('_', ' ')}</td></tr>`;
      list += "</table>";
      let marks = await getMarks(subj);
      $("section").innerHTML = list + marks;
      $("#marks").scrollLeft = $("#marks").scrollWidth;

      // Блок ввода/редактирования урока
      let edit = `<input id="dt" type="date" value="${dtNow}">
         <textarea id="topUr"
            placeholder="Тема урока\n(пустая тема => удаление колонки)"
            ></textarea>
         <textarea id="htask" placeholder="Домашнее задание"></textarea>
         Часов <input id="val" type="number" min="1" max="6" value="2">
         &emsp;Вес <input id="wgh" type="number" min="0" max="10" step="0.5" value="1">
         <button type="button" onclick="sv()">&gt;&gt;</button>
         <article></article>`;
      $("aside").innerHTML = edit;
      showTopics(subj); // показываем список тем
   }
   
   // Если это учащийся или родитель
   else {
      $("aside").style.display  = "none";
      $("section").style.width  = "calc(100% - 16px)";
      $("section").style.border = "none";
      $("section").style.background  = "transparent";
      $("section").innerHTML = await onePup(subj);
   }
}
